package com.leyou.trade.service.impl;

import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.leyou.auth.utils.UserContext;
import com.leyou.common.exception.LyException;
import com.leyou.item.client.ItemClient;
import com.leyou.item.dto.SkuDTO;
import com.leyou.trade.dto.OrderDTO;
import com.leyou.trade.entity.Order;
import com.leyou.trade.entity.OrderDetail;
import com.leyou.trade.entity.OrderLogistics;
import com.leyou.trade.mapper.OrderMapper;
import com.leyou.trade.service.OrderDetailService;
import com.leyou.trade.service.OrderLogisticService;
import com.leyou.trade.service.OrderService;
import com.leyou.user.client.UserClient;
import com.leyou.user.dto.AddressDTO;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.apache.ibatis.annotations.Select;
import org.joda.time.DateTime;
import org.springframework.amqp.core.AmqpTemplate;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.util.*;
import java.util.stream.Collectors;

import static com.leyou.common.constants.MQConstants.ExchangeConstants.ORDER_EXCHANGE_NAME;
import static com.leyou.common.constants.MQConstants.RoutingKeyConstants.EVICT_ORDER_KEY;

@Service
@Slf4j
public class OrderServiceImpl extends ServiceImpl<OrderMapper, Order> implements OrderService {

    @Autowired
    private ItemClient itemClient;

    @Autowired
    private OrderDetailService detailService;

    @Autowired
    private UserClient userClient;

    @Autowired
    private OrderLogisticService logisticService;

    @Autowired
    private AmqpTemplate amqpTemplate;


    @Override
    @Transactional
    public Long createOrder(OrderDTO orderDTO) {
        //总价 carts商品的单价*数量累加

        //carts的key是sku的id,value就是当前id对应的数量
        Map<Long, Integer> carts = orderDTO.getCarts();

        //减库存,业务成功，业务完成时减库存的事务就提交了
        this.itemClient.minusStock(carts);


        long start = System.currentTimeMillis();

        Long userId = UserContext.getUser().getId();

        //以orderDTO为源，创建生成三个表中的数据

        Order order = new Order();



        List<Long> ids = new ArrayList<>(carts.keySet());

        //id有值才能去查询没有值，查询报错400
        if (null != ids && 0 != ids.size()) {

            List<SkuDTO> skuDTOS = this.itemClient.querySkuByIds(ids);

            //总价
            long totalPrice = 0;
            for (SkuDTO skuDTO : skuDTOS) {

                Long skuId = skuDTO.getId();
                Long price = skuDTO.getPrice();

                Integer num = carts.get(skuId);

                totalPrice+=price*num;
            }

            order.setTotalFee(totalPrice);
            order.setActualFee(totalPrice);
            order.setPaymentType(orderDTO.getPaymentType());
            order.setPostFee(0L);
            order.setUserId(userId);
            order.setStatus(1);
            //保存order订单并回显id
            save(order);

            List<OrderDetail> orderDetails = new ArrayList<>();
            for (SkuDTO skuDTO : skuDTOS) {
                OrderDetail orderDetail = new OrderDetail();

                orderDetail.setOrderId(order.getOrderId());

                orderDetail.setSkuId(skuDTO.getId());
                orderDetail.setNum(carts.get(skuDTO.getId()));
                orderDetail.setTitle(skuDTO.getTitle());
                orderDetail.setSpec(skuDTO.getSpecialSpec());
                orderDetail.setPrice(skuDTO.getPrice());
                //从逗号开始截取，图片中的第一个图
                orderDetail.setImage(StringUtils.substringBefore(skuDTO.getImages(),","));

                orderDetails.add(orderDetail);
            }

            //批量保存orderDetail
            this.detailService.saveBatch(orderDetails);


            AddressDTO addressDTO = this.userClient.queryAddressByIdAndUserId(orderDTO.getAddressId(), userId);

            OrderLogistics logistics = new OrderLogistics();

            BeanUtils.copyProperties(addressDTO,logistics);

            logistics.setOrderId(order.getOrderId());

            //保存物流
            this.logisticService.save(logistics);

            long end = System.currentTimeMillis();


            log.info("本次下单业务耗时{}ms",end-start);


            //把orderId保存给redis，作为key，保存20min，20min键过期，键过期通知，自动获取到存储的key

            //此时写监听器，看监控的订单是否已经支付，如未支付，则，关闭订单

            //下单及发送消息到mq，mq中的死信队列会对消息延迟
            amqpTemplate.convertAndSend(ORDER_EXCHANGE_NAME, EVICT_ORDER_KEY, order.getOrderId());

            return order.getOrderId();

            //请求微信，生成支付链接

        }else{
            throw new LyException(400,"下单必须选中至少一件商品");
        }

    }

    @Override
    @Transactional
    public void closeOrder() {
        //deadLine,2020/10/17 09:00:00 2020/10/17 09:20:00

        //if currentTime-20min greater than createTime

        Date deadLine = DateTime.now().minusMinutes(20).toDate();

        //select * from tb_order where status = 1 and create_time < deadLine

        List<Order> orders = query().eq("status", 1)
                .lt("create_time", deadLine)
                .list();

        if (null==orders||0==orders.size()){
            return;
        }

        orders.forEach(order->order.setStatus(5));
        //批量关闭订单
        updateBatchById(orders);

        //找出当前订单关闭时需要还原的 所有 的商品的 所有 库存

        //select * from tb_order_detail where  order_id in(xxx)

        plusStockByOrder(orders);

    }

    private void plusStockByOrder(List<Order> orders) {
        List<OrderDetail> orderDetails =
                this.detailService
                        .query()
                        .in("order_id",
                                orders.stream().map(Order::getOrderId).collect(Collectors.toSet())).list();

        //从orderDetails中取出所有商品

        Map<Long,Integer> skuMap = new HashMap<>();

        orderDetails.forEach(orderDetail -> {

            Long key = orderDetail.getSkuId();

            Integer num = orderDetail.getNum();

            //已经加入过，修改数量
            if (skuMap.containsKey(key)){
                skuMap.put(key,skuMap.get(key)+num);
            }else{
                skuMap.put(key,num);
            }

        });


        //加库存
        this.itemClient.plusStock(skuMap);
    }

    @Override
    @Transactional
    public void evictOrderIfNecessary(Long orderId) {
        //查验订单，是否需要清理，订单状态是否为1
        Order order = getById(orderId);
        if (1==order.getStatus()){
            order.setStatus(5);
            order.setUpdateTime(new Date());
            updateById(order);

            //加库存
            plusStockByOrder(Arrays.asList(order));
        }
    }
}
